package com.pep.mgmt.service;

import java.io.File;
import java.util.Calendar;
import java.util.List;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import com.pep.mgmt.model.entity.ConfigEntity;
import com.pep.mgmt.model.entity.RunningEntity;
import com.pep.mgmt.util.CONST;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class SchedulerService {

    private final PepMgmtService pepMgmtService;
    private final ShellCmdService shellCmdService;
    private boolean isStarted;

    public void startSchedulerService() {
        isStarted = true;
    }

    public void stopSchedulerService() {
        isStarted = false;
    }

    private void logFileCleanupCommon(String filePath) {

        Calendar calendar = Calendar.getInstance(); //得到日历
        calendar.add(Calendar.DATE, -CONST.LOG_KEEP_DATE);
        //转换成时间戳
        long t1 = calendar.getTime().getTime();
        File f = new File(filePath);
        File[] files = f.listFiles();
        if (files != null) {
            for (File file : files) {
                //获取文件最后一次被修改的时间
                Long lastTime = file.lastModified();
                if ((lastTime < t1) && file.exists() && file.isFile()) {
                    //判断文件是否存在和是否是一个标准文件
                    log.info("try to delete log file {}", file.getAbsolutePath());
                    try {
                        if (file.delete()) {
                            log.info("delete log file successfully");
                        } else {
                            log.warn("failed to delete the log file");
                        }
                    } catch (SecurityException ex) {
                         log.warn("clean up log file error {}", ex.getMessage());
                    }
                }
            }
        }
    }

    @Scheduled(cron = "0 0 0 * * *")
    public void logFileCleanup() {
        log.info("launched file cleanup handler");
        logFileCleanupCommon(CONST.LOG_FILE_PATH);
        log.info("launched file cleanup additional handler");
        logFileCleanupCommon(CONST.LOG_FILE_PATH_ADDITIONAL);
    }
    public SchedulerService(PepMgmtService pepMgmtService, ShellCmdService shellCmdService) {
        this.pepMgmtService = pepMgmtService;
        this.shellCmdService = shellCmdService;
        isStarted = false;
    }

    @Scheduled(fixedDelay = 2000)
    public void runningProgramKeepalive() {
        if (!isStarted)
            return;
        List<RunningEntity> runningProgramEntityList = pepMgmtService.findAllRunningPrograms();
        log.info("runningProgramKeepalive size in database {}", runningProgramEntityList.size());
        String result = null;
        if (CONST.TEST_MODE) 
            result = shellCmdService.someMethod("pidof " + CONST.TEST_PROGRAM_NAME);
        else 
            result = shellCmdService.someMethod("pidof " + CONST.PEP_PROGRAM_NAME);
        int pidNumber = 0;
        if (!result.isEmpty()) {
            String[] pidStrings = result.split(" ");
            pidNumber = pidStrings.length;
        }
        log.info("result size {}\n\r{}", pidNumber, result);
        if (pidNumber != runningProgramEntityList.size()) {
            log.warn("size in database {}, while size in running {}", runningProgramEntityList.size(), pidNumber);
        }

        List<ConfigEntity> configEntities = pepMgmtService.getConfig();
        boolean isConfigUpdated = false;
        for (ConfigEntity ce : configEntities) {
            isConfigUpdated = ce.isPendingConfigUpdate();
            if (isConfigUpdated) {
                pepMgmtService.clearPendingConfigUpdate();
            }
        }
        
        for (RunningEntity item : runningProgramEntityList) {
            log.info("vrf: {}, pid: {}", item.getVrfName(), item.getPId());
            if (result.contains(item.getPId().toString())) {
                if (item.isRequiredStopped()) {
                    pepMgmtService.removeRunningProgram(item.getVrfName());
                    log.info("Pid {} marked dead, so kill the program!", item.getPId());
                    shellCmdService.someMethod("kill " + item.getPId());
                    continue;
                } 
                
                if (isConfigUpdated) {
                    log.info("the config is updated, need to reload the config");
                    log.info("run kill -s SIGHUP {}", item.getPId());
                    shellCmdService.someMethod("kill -s SIGHUP " + item.getPId());
                }
            
            } else {
                String res = null;

                if (item.isRequiredStopped()) {
                    pepMgmtService.removeRunningProgram(item.getVrfName());
                    continue;
                }
                log.info("attempt to restart {}", item);
                if (CONST.TEST_MODE)
                    res = shellCmdService.someMethod("./start_program.sh " + item.getVrfName() + " " + item.getLaunchCmd());
                else 
                    res = shellCmdService.someMethod("./bash/start_tcp.sh " + item.getVrfName() + " " + item.getLocalBindIpAddr() + " " + item.getWorkMode());
                
                log.info("result to restart {}", res);
                long pId = -1;
                try {
                    pId = Long.parseLong(res.trim());
                    log.info("restart {} with new pId {}", item, pId);
                } catch (NumberFormatException nfe) {
                    log.warn("NumberFormatException {}", nfe.getMessage());
                }
                if (pId > 0)
                    pepMgmtService.updateRunningProgramPid(item, pId);
            }   
        }
    
        // if (CONST.TEST_MODE)
        //     shellCmdService.someMethod("killall " + CONST.TEST_PROGRAM_NAME);
        // else 
        //     shellCmdService.someMethod("killall " + CONST.PEP_PROGRAM_NAME);
    }

}
